package com.qfedu;

/**
 * @version java version 1.8
 * @Author: LiJH
 * @description:
 * @date: ${YEAR}-${MONTH}-${DAY} ${TIME}
 */
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.LinkedList;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class SnakeGame extends JPanel implements KeyListener, Runnable {
    private static final long serialVersionUID = 1L;
    private static final int WIDTH = 500;
    private static final int HEIGHT = 500;
    private static final int DOT_SIZE = 10;
    private static final int INITIAL_SNAKE_LENGTH = 5;
    private static final int SLEEP_TIME = 100;
    private static final int FOOD_COLOR = 0xFF0000; // 红色
    private static final int SNAKE_COLOR = 0x00FF00; // 绿色
    private static final int BACKGROUND_COLOR = 0x000000; // 黑色

    private LinkedList<Point> snake;
    private Point food;
    private int direction;
    private Random rand;

    public SnakeGame() {
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        setBackground(Color.BLACK);
        addKeyListener(this);
        setFocusable(true);

        snake = new LinkedList<Point>();
        direction = KeyEvent.VK_RIGHT;
        rand = new Random();

        // 初始化贪吃蛇的位置和长度
        for (int i = 0; i < INITIAL_SNAKE_LENGTH; i++) {
            snake.add(new Point(WIDTH / 2 - i * DOT_SIZE, HEIGHT / 2));
        }

        // 随机生成食物
        generateFood();
    }

    private void generateFood() {
        int x = rand.nextInt(WIDTH / DOT_SIZE) * DOT_SIZE;
        int y = rand.nextInt(HEIGHT / DOT_SIZE) * DOT_SIZE;
        food = new Point(x, y);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        // 绘制贪吃蛇
        g.setColor(new Color(SNAKE_COLOR));
        for (Point p : snake) {
            g.fillRect(p.x, p.y, DOT_SIZE, DOT_SIZE);
        }

        // 绘制食物
        g.setColor(new Color(FOOD_COLOR));
        g.fillRect(food.x, food.y, DOT_SIZE, DOT_SIZE);
    }

    private void move() {
        // 计算蛇头的新位置
        Point head = snake.getFirst();
        Point newHead = new Point(head);
        switch (direction) {
            case KeyEvent.VK_UP:
                newHead.y -= DOT_SIZE;
                break;
            case KeyEvent.VK_DOWN:
                newHead.y += DOT_SIZE;
                break;
            case KeyEvent.VK_LEFT:
                newHead.x -= DOT_SIZE;
                break;
            case KeyEvent.VK_RIGHT:
                newHead.x += DOT_SIZE;
                break;
        }

        // 判断是否吃到食物
        if (newHead.equals(food)) {
            snake.addFirst(food);
            generateFood();
        } else {
            // 移动贪吃蛇
            snake.removeLast();
            snake.addFirst(newHead);
        }

        // 判断是否碰到边界或自身
        if (newHead.x < 0 || newHead.x >= WIDTH || newHead.y < 0 || newHead.y >= HEIGHT || snake.contains(newHead)) {
            gameOver();
        }
    }

    private void gameOver() {
        System.out.println("Game Over!");
        System.exit(0);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_UP && direction != KeyEvent.VK_DOWN) {
            direction = KeyEvent.VK_UP;
        } else if (key == KeyEvent.VK_DOWN && direction != KeyEvent.VK_UP) {
            direction = KeyEvent.VK_DOWN;
        } else if (key == KeyEvent.VK_LEFT && direction != KeyEvent.VK_RIGHT) {
            direction = KeyEvent.VK_LEFT;
        } else if (key == KeyEvent.VK_RIGHT && direction != KeyEvent.VK_LEFT) {
            direction = KeyEvent.VK_RIGHT;
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyReleased(KeyEvent e) {}

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            move();
            repaint();
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Snake Game");
        SnakeGame game = new SnakeGame();
        frame.add(game);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        new Thread(game).start();
    }
}